/*
 * @Author: xiaoyan
 * @Date: 2021-09-30 10:05:38
 * @LastEditors: xiaoyan
 * @LastEditTime: 2021-10-10 16:36:09
 * @Description: tab页签
 * @FilePath: \vue3-ts-demo\src\store\modules\tagsview.ts
 */
import {
    Store as VuexStore,
    CommitOptions,
    Module,
    DispatchOptions,
    ActionContext,
  } from 'vuex'
import { RootState } from '@/store'
import { RouteLocationNormalized } from 'vue-router'

export interface TagView extends Partial<RouteLocationNormalized> {
    title?: string,
}

export interface TagsViewState {
    visitedViews: TagView[]
    cachedViews: (string | undefined)[]
}

export type Mutations<S = TagsViewState> = {
    ADD_VISITED_VIEW(state: S, view: TagView): void
    ADD_CACHED_VIEW(state: S, view: TagView): void
    DEL_VISITED_VIEW(state: S, view: TagView): void
    DEL_CACHED_VIEW(state: S, view: TagView): void
    DEL_OTHERS_VISITED_VIEWS(state: S, view: TagView): void
    DEL_OTHERS_CACHED_VIEWS(state: S, view: TagView): void
    DEL_ALL_VISITED_VIEWS(state: S): void
    DEL_ALL_CACHED_VIEWS(state: S): void
    UPDATE_VISITED_VIEW(state: S, view: TagView): void
}
type AugmentedActionContext = {
    commit<K extends keyof Mutations>(
      key: K,
      payload: Parameters<Mutations[K]>[1],
    ): ReturnType<Mutations[K]>
  } & Omit<ActionContext<TagsViewState, RootState>, 'commit'>
  
type NoAugmentedActionContext = {
    commit<K extends keyof Mutations>(
      key: K,
    ): ReturnType<Mutations[K]>
  } & Omit<ActionContext<TagsViewState, RootState>, 'commit'>

export interface Actions {
    AddView({commit}:AugmentedActionContext,view: TagView):void
    AddVisitedView({commit}:AugmentedActionContext,view: TagView):void
    DelView({commit}:AugmentedActionContext,view: TagView):void
    DelOtherView({commit}:AugmentedActionContext,view: TagView):void
    DelCachedView({commit}:AugmentedActionContext,view: TagView):void
    OtherVierws({commit}:AugmentedActionContext,view: TagView):void
    DelAllViews({commit}:NoAugmentedActionContext):void
    DelAllCachedViews({commit}:NoAugmentedActionContext):void
    UpdateVisitedView({commit}:AugmentedActionContext,view: TagView):void
}

export type TagsStore<S = TagsViewState> = Omit<VuexStore<S>, 'getters' | 'commit' | 'dispatch'>
& {
  commit<K extends keyof Mutations, P extends Parameters<Mutations[K]>[1]>(
    key: K,
    payload: P,
    options?: CommitOptions
  ): ReturnType<Mutations[K]>
} & {
  dispatch<K extends keyof Actions>(
    key: K,
    payload: Parameters<Actions[K]>[1],
    options?: DispatchOptions
  ): ReturnType<Actions[K]>
};

export const store: Module<TagsViewState, RootState> = {
    getters:{
        
    },
    state:{
        visitedViews: [],
        cachedViews: []
    },
    mutations:{
        ADD_VISITED_VIEW:(state: TagsViewState, view: TagView)=>{
            if (state.visitedViews.some(v => v.path === view.path)) return
            state.visitedViews.push(
                Object.assign({}, view, {
                    title: view.meta?.title || 'no-name'
                })
            )
        },
        ADD_CACHED_VIEW:(state: TagsViewState, view: TagView)=>{
            if (view.name === null) return
            if (state.cachedViews.includes(view.name?.toString())) return
            if (!view.meta?.noCache) {
                state.cachedViews.push(view.name?.toString())
            }
        },
        DEL_VISITED_VIEW:(state: TagsViewState, view: TagView)=>{
            for (const [i, v] of state.visitedViews.entries()) {
                if (v.path === view.path) {
                    state.visitedViews.splice(i, 1)
                    break
                }
            }
        },
        DEL_CACHED_VIEW:(state: TagsViewState, view: TagView)=>{
            if (view.name === null) return
            const index = state.cachedViews.indexOf(view.name?.toString())
            index > -1 && state.cachedViews.splice(index, 1)
        },

        DEL_OTHERS_VISITED_VIEWS:(state: TagsViewState, view: TagView)=>{
            state.visitedViews = state.visitedViews.filter(v => {
                return v.meta?.affix || v.path === view.path
            })
        },
        DEL_OTHERS_CACHED_VIEWS:(state: TagsViewState, view: TagView)=>{
            if (view.name === null) return
            const index = state.cachedViews.indexOf(view.name?.toString())
            if (index > -1) {
                state.cachedViews = state.cachedViews.slice(index, index + 1)
            } else {
                state.cachedViews = []
            }
        },
        DEL_ALL_VISITED_VIEWS:(state: TagsViewState)=>{
            const affixTags = state.visitedViews.filter(tag => tag.meta?.affix)
            state.visitedViews = affixTags
        },
        DEL_ALL_CACHED_VIEWS:(state: TagsViewState)=>{
            state.cachedViews = []
        },
        UPDATE_VISITED_VIEW:(state: TagsViewState, view: TagView)=>{
            for (let v of state.visitedViews) {
                if (v.path === view.path) {
                    v = Object.assign(v, view)
                    break
                }
            }
        },

    },
    actions:{
        AddView({commit},view: TagView){
            commit('ADD_VISITED_VIEW', view)
            commit('ADD_CACHED_VIEW', view)
        },

        AddVisitedView({commit},view: TagView){
            commit('ADD_VISITED_VIEW', view)
        },
        DelView({commit},view: TagView){
            commit('DEL_VISITED_VIEW', view)
            commit('DEL_CACHED_VIEW', view)
        },
        DelOtherView({commit},view: TagView){
            commit('DEL_OTHERS_VISITED_VIEWS', view)
            commit('DEL_OTHERS_CACHED_VIEWS', view)
        },
        DelCachedView({commit},view: TagView){
            commit('DEL_CACHED_VIEW', view)
        },
        OtherVierws({commit},view: TagView){
            commit('DEL_OTHERS_VISITED_VIEWS', view)
            commit('DEL_OTHERS_CACHED_VIEWS', view)
        },
        DelAllViews({commit}){
            commit('DEL_ALL_VISITED_VIEWS')
            commit('DEL_ALL_CACHED_VIEWS')
        },
        DelAllCachedViews({commit}){
            commit('DEL_ALL_CACHED_VIEWS')
        },
        UpdateVisitedView({commit},view: TagView){
            commit('UPDATE_VISITED_VIEW', view)
        },
    },

}